package cn.dqy.gotanserver.support.aspect;

import cn.dqy.gotanserver.anno.CheckOnline;
import cn.dqy.gotanserver.code.GoTanDtoDecode;
import cn.dqy.gotanserver.dto.R;
import cn.dqy.gotanserver.service.CoreServer;
import cn.dqy.gotanserver.support.ClientRespondRecordUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

@Component
@Aspect
public class CheckOnlineAspect {
    static Logger logger = LoggerFactory.getLogger(CheckOnlineAspect.class);

    @Autowired
    CoreServer coreServer;

    @Autowired
    ClientRespondRecordUtils clientRespondRecordUtils;

    @Pointcut(value = "@annotation(cn.dqy.gotanserver.anno.CheckOnline)")
    public void pj() { }

    @Around("pj()")
    public Object  beforeAdvice(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        String target = (String) args[0];

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        CheckOnline annotation = signature.getMethod().getAnnotation(CheckOnline.class);
        String remark = annotation.remark();
        printArgs(args,remark);

        logger.info("[AOP] 校验目标机器在线切面,从{}方法进入",remark);
        Set<String> onlineClient = coreServer.getOnlineClient();

        logger.info("[AOP] 校验目标机器: {}",target);
        if(null==target || !onlineClient.contains(target)){
            logger.info("[AOP] 校验在线不通过，目标机器不在线");
            return R.build(400,target + "不在线","找不到目标机器");
        }
        try {
            return joinPoint.proceed(args);
        } catch (Throwable throwable) {
            String errStr = String.format("执行 %s 异常,原因 %s", remark, throwable.getMessage());
            clientRespondRecordUtils.wInfo(errStr,true,false);
            logger.error("[AOP] 执行方法內异常 原因",throwable);
            throwable.printStackTrace();
        }
        return R.build(500,"严重错误","服务器内部错误");
    }

    private void printArgs(Object[] args,String rk){
        StringBuilder builder=new StringBuilder();
        for (Object ag:args){
            builder.append(ag+",");
        }
        logger.info("[AOP] {}入参 : {}",rk,builder.toString());
    }
}
